/*
App.cpp
主函数写在这里
*/

#include <oatpp/web/client/HttpRequestExecutor.hpp>
#include <oatpp/network/tcp/client/ConnectionProvider.hpp>
#include <oatpp/parser/json/mapping/ObjectMapper.hpp>
#include <atomic>
#include <thread>
#include <mutex>
#include <condition_variable>
#include "DataTransmit.hpp"
#include "newDataEvent.hpp"
#include "DeviceClient.hpp"
#include "DeviceInfo.h"
#include <iostream>
#include <random>
#include <utility>
#include <fstream>
#include "systemInfo.hpp"

std::condition_variable clientExitCond;
std::mutex clientExitFlag;

std::condition_variable clientNewDataCond;
std::mutex receivedNewData;
std::atomic<float> CPUValue;
std::atomic<float> MEMValue;
std::atomic<bool> newDataFlag;

class DeviceCollege
{
    public:
        DeviceCollege()
        {
        }
        DeviceCollege& operator() ()
        {
            while (!exitFlag.load())
            {
                std::this_thread::sleep_for(std::chrono::milliseconds(1000));
                CPUValue=sysInfo.getCPUusage();
                MEMValue=sysInfo.getMemoryUsage();
                newDataFlag.store(true);
                clientNewDataCond.notify_one();
                //OATPP_LOGI("Sensor","Received Data 1");
            }
            clientExitCond.notify_all();
            return *this;
        }
        bool static getExitFlag()
        {
            return exitFlag.load();
        }
        static std::atomic<bool> exitFlag;  //多线程环境，原子变量同步
    private:
        SystemInfo sysInfo;
};

std::atomic<bool> DeviceCollege::exitFlag=false;

class Client
{
    private:
        std::shared_ptr<DeviceClient> _client;
    public:
        Client()=default;
        void sendNewData()
        {
            while (!DeviceCollege::getExitFlag())
            {
                std::unique_lock<std::mutex> lk(receivedNewData);
                clientNewDataCond.wait(lk,[]{return newDataFlag.load();});
                newDataFlag.store(false);
                lk.unlock();
                DataTransmit::UploadData(_client,CPUValue.load(),MEMValue.load());
            }
        }

        Client& operator() ()
        {
            auto objectMapper=oatpp::parser::json::mapping::ObjectMapper::createShared();
            OATPP_LOGI("Client","Client start on %s : %d",ServerPath,ServerPort);
            auto connectionProvider=oatpp::network::tcp::client::ConnectionProvider::createShared({ServerPath,ServerPort});
            auto requestExecutor=oatpp::web::client::HttpRequestExecutor::createShared(connectionProvider);
            _client=DeviceClient::createShared(requestExecutor,objectMapper);
            
            sendNewData();

            return *this;
        }
};


int main()
{
    oatpp::base::Environment::init();

    DeviceCollege sensorA;
    Client NetworkClient;

    std::thread sensorCollegeT(sensorA);
    std::thread networkClientT(NetworkClient);

    sensorCollegeT.join();
    networkClientT.join();

    oatpp::base::Environment::destroy();
}